import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.*;

/**
 * 
 * 
 * @author Ulises Yamil Castorena Caldera
 * @version 1.0
 */
public class DuckWorld extends World
{
    private int nivel;    
    private int cantDuck;
    private int score;
    private int scoreE;
    private int cont;
    private int gano;
    private User personaje;
    private Enemy enemigo;
    private Dog perro;
    private Text textoNivel;
    private boolean ready;
    private boolean enable;
    private boolean enableW;
    private boolean fin;
    private boolean valida;
    private GreenfootSound son;
    private GreenfootSound start;      

    /**
     * Constructor for objects of class DuckWorld.
     * 
     */
    public DuckWorld()
    {       
        super(600, 400, 1); 
        score = 0;                
        nivel = 0;       
        cont = 0;   
        gano = 1;
        valida = false;
        ready = false;
        enable = false;
        fin = false;
        enableW = false;
        son = new GreenfootSound("Title.mp3");
        start = new GreenfootSound("start.mp3");           
        portada();
    }   
    
    /**
     * Método act de la clase.
     */
    public void act()
    {   
        if(nivel == 0)
            son.play();
        else
            son.stop();
        if(!enable)
            prepare();
        else 
        {
            if(ready)
                nivel();
            else
               inicioNivel();
        }
        if(fin)
        {
            if(!enableW)            
                finNivel();
            else
            {
                if(nivel != 0)
                    incrementaNivel();            
                limpia();
                fin = false;
                enableW = false;
                if(nivel == 0)
                {
                    score = 0;
                    portada();
                    gano = 1;
                }
            }            
        }
    }
    
    /**
     * 
     */
    public void portada()
    {
        addObject(new Background(1),getWidth()/2,getHeight()/2);
        addObject(new TextBack(0),300,200);
        addObject(new TextBack(1),300,250);
        addObject(new TextBack(2),300,300);
    }
    
    /**
     * Método que prepara el mundo dependiendo del nivel en el que este.
     */
    public void prepare()    
    {           
        if(nivel == 1 || nivel == 2)
        {            
            personaje = new User();                        
            if(nivel == 1)
                cantDuck = 30;
            else
                cantDuck = 40;              
            addObject(new Background(0),getWidth()/2,getHeight()/2);
            addObject(personaje,getWidth()/2,getHeight()/2);    
            addObject(new Text("Ducks",cantDuck,0),getWidth()/2,350);
            addObject(new Text("Score",score,1),50,370);
            addObject(new Text("Ammo",personaje.returnAmmo(),2),50,350);   
            enable = true;
        }
        else if(nivel == 3)
        {
            enemigo = new Enemy();
            personaje = new User();            
            cantDuck = 50;            
            scoreE = score;          
            addObject(new Background(0),getWidth()/2,getHeight()/2);
            addObject(personaje,getWidth()/2,getHeight()/2);    
            addObject(enemigo,getWidth()/2,getHeight()/2);    
            addObject(new Text("Ducks",cantDuck,0),getWidth()/2,350);
            addObject(new Text("Score",score,1),50,370);
            addObject(new Text("Score",scoreE,4),550,370);
            addObject(new Text("Ammo",personaje.returnAmmo(),2),50,350);            
            addObject(new Text("Ammo Inf",6),550,350);
            enable = true;
        }
    }       
    
    /**
     * Método que regresa un objeto, para 
     */
    public Object character()
    {
        return personaje;
    }
    
    /**
     * Manda llamar a los objetos dependiendo del nivel.
     */
    public void nivel()
    {           
        int a;
        switch(nivel)
        {
            case 1:                
                a = Greenfoot.getRandomNumber(2);
                if(cantDuck != 0)
                {                      
                    if(Greenfoot.getRandomNumber(50) == 5)
                    {                    
                        if(a == 0)
                            addObject(new Duck(a),0,Greenfoot.getRandomNumber((getHeight())/2) + 50);
                        else 
                            addObject(new Duck(a),getWidth(),Greenfoot.getRandomNumber((getHeight()/2)) + 50);
                        cantDuck --;
                    }
                    if(Greenfoot.getRandomNumber(50) == 5)
                    {                
                        if(a == 0)
                            addObject(new Falcon(1),0,Greenfoot.getRandomNumber((getHeight())/2) + 50);
                        else 
                            addObject(new Falcon(0),getWidth(),Greenfoot.getRandomNumber((getHeight()/2)) + 50);
                    }           
                    if(Greenfoot.getRandomNumber(100) == 0)  
                        addObject(new Lion(),0,300);
                }
            break;
            case 2:                    
                a = Greenfoot.getRandomNumber(2);
                if(cantDuck != 0)
                {                      
                    if(Greenfoot.getRandomNumber(10) == 5)
                    {                    
                        if(a == 0)
                            addObject(new Duck(a),0,Greenfoot.getRandomNumber((getHeight())/2) + 50);
                        else 
                            addObject(new Duck(a),getWidth(),Greenfoot.getRandomNumber((getHeight()/2)) + 50);
                        cantDuck --;
                    }
                    if(Greenfoot.getRandomNumber(20) == 5)
                    {                
                        if(a == 0)
                            addObject(new Falcon(1),0,Greenfoot.getRandomNumber((getHeight())/2) + 50);
                        else 
                            addObject(new Falcon(0),getWidth(),Greenfoot.getRandomNumber((getHeight()/2)) + 50);
                    }
                    if(Greenfoot.getRandomNumber(100) == 0)  
                        addObject(new Lion(),0,300);
                }
            break;
            case 3:
                a = Greenfoot.getRandomNumber(2);
                if(cantDuck != 0)
                {                      
                    if(Greenfoot.getRandomNumber(10) == 5)
                    {                    
                        if(a == 0)
                            addObject(new Duck(a),0,Greenfoot.getRandomNumber((getHeight())/2) + 50);
                        else 
                            addObject(new Duck(a),getWidth(),Greenfoot.getRandomNumber((getHeight()/2)) + 50);
                        cantDuck --;
                    }
                    if(Greenfoot.getRandomNumber(10) == 5)
                    {                
                        if(a == 0)
                            addObject(new Falcon(1),0,Greenfoot.getRandomNumber((getHeight())/2) + 50);
                        else 
                            addObject(new Falcon(0),getWidth(),Greenfoot.getRandomNumber((getHeight()/2)) + 50);
                    }                    
                }
            break;
        }
        if(cantDuck == 0)
        {
            List lista = getObjects(Duck.class);            
            if(lista.isEmpty())            
                fin = true;                            
        }
    }
    
    /**
     * Cambia el estado de enable a false y elimina todos los objetos del mundo.
     */
    public void limpia()
    {
        enable = false;
        ready = false;
        valida = false;
        removeObjects(getObjects(null));  
        cont = 0;
    }
    
    /**
     * @return Regresa el nivel actual en el que el juego se encuentra.
     */
    public int returnNivel()
    {
        return nivel;
    }
    
    /**
     * @return Regresa el valor de los patos que faltan por salir.
     */
    public int returnCant()
    {
        return cantDuck;
    }
    
    /**
     * @return Regresa el valor del puntaje.
     */
    public int returnScore()
    {
        return score;
    }   
    
    /**
     * 
     */
    public int returnScoreEnemy()
    {
        return scoreE;
    }
    
    /**
     * Incrementa el valor del score segun el valor recibido.
     * @param valor El valor a sumar
     */
    public void incrementaScore(int valor)
    {
        score = score + valor;
    }
    
    /**
     * 
     */
    public void incrementaScoreEnemy(int valor)
    {
        scoreE = scoreE + valor;
    }
    
    /**
     * Incrementa el nivel
     */
    public void incrementaNivel()
    {
        nivel++;
    }
    
    /**
     * Método utilizado para la creación del letrero que indica el nivel, así como de la creación del objeto del perro
     * que se muestra.
     */
    public void inicioNivel()
    {
        if(!enableW)
        {                    
            cont++; 
            if(cont == 1)
            {
                textoNivel = new Text("Nivel  ",nivel,3);                
                addObject(textoNivel,getWidth()/2,getHeight()/2); 
                start.play();               
            }
            else if(cont == 70)
            {
                removeObject(textoNivel);
                cont = 0;
                enableW = true;
                addObject(new Dog(0),7,290);
            }
        }
        else
        {            
            cont++;
            if(cont == 70)   
            {
                ready = true;
                enableW = false;
                cont = 0;
            }
        }
    } 
    
    /**
     * 
     */
    public void finNivel()
    {
        if(nivel < 3 && nivel > 0)                    
            salPerro();
        else        
            fin();
    }   
    
    public void salPerro()
    {
        cont++;
        if(cont == 1)
        {
            addObject(new Dog(gano),getWidth()/2,231);
            removeObjects(getObjects(Targets.class));
        }
        if(cont == 45)
        {
            if(!valida)
                enableW = true;
            else
            {
                nivel = 0;                
                enableW = true;
            }
        }
    }
    
    public void fin()
    {
        if(!valida)
        {            
            if(score > scoreE)            
            {
                addObject(new Text("Haz Ganado\nYou Win",5),getWidth()/2,getHeight()/2 - 50);            
                gano = 2;
            }
            else            
            {
                addObject(new Text("Haz Perdido\nYou Lose",5),getWidth()/2,getHeight()/2 - 50);            
                gano = 1;
            }
            valida = true;
        }        
        else        
            salPerro();        
    }
}
